import { extname } from 'path';

import { v4 as uuid4 } from 'uuid';
import { diskStorage } from 'multer';
import {
  Controller,
  HttpException,
  HttpStatus,
  Post,
  UseInterceptors,
  UploadedFile,
} from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';
import {
  ApiBody,
  ApiConsumes,
  ApiOperation,
  ApiResponse,
  ApiTags,
} from '@nestjs/swagger';

import { Public } from '../../auth/auth.decorator';
import { Response } from '../../../infra/schema/response';
import { UploadImageDto, UploadFileDto } from './upload.schema';
import { env } from '../../../settings';
import { getCurrentDate } from '../../../infra/common/utils';
import { log } from 'console';

const getUploadImageType = () => {
  const fileType = env.UPLOAD_IMG_EXT.join('|');
  return new RegExp(`image\/(${fileType})`);
};

const imageUploadOptions = {
  limits: {
    fileSize: env.UPLOAD_IMG_MAX_FILE_SIZE,
  },
  fileFilter: (req, file, cb) => {
    const regex = getUploadImageType();
    if (file.mimetype.match(regex)) {
      // Allow storage of file
      cb(null, true);
    } else {
      // Reject file
      cb(
        new HttpException(
          `Unsupported file type ${extname(file.originalname)}`,
          HttpStatus.BAD_REQUEST,
        ),
        false,
      );
    }
  },
  storage: diskStorage({
    destination: `./uploads/image/${getCurrentDate(false)}`,
    filename: (req, file, cb) => {
      const uuid = req['requestId'] || uuid4();
      // Generate a unique filename with the original extension
      cb(null, uuid + extname(file.originalname));
    },
  }),
};
const videoUploadOptions = {
  limits: {
    fileSize: env.UPLOAD_VIDEO_MAX_FILE_SIZE,
  },
  fileFilter: (req, file, cb) => {
    const allowedFileTypes = env.UPLOAD_VIDEO_EXT;
    const fileExtension = file.originalname.split('.').pop().toLowerCase();
    if (allowedFileTypes.includes(fileExtension)) {
      // 允许存储文件
      cb(null, true);
    } else {
      // 拒绝文件
      cb(
        new HttpException(
          `Unsupported file type ${extname(file.originalname)}`,
          HttpStatus.BAD_REQUEST,
        ),
        false,
      );
    }
  },
  storage: diskStorage({
    destination: `./uploads/videos/${getCurrentDate(false)}`,
    filename: (req, file, cb) => {
      const uuid = req['requestId'] || uuid4();
      // 生成带原始扩展名的唯一文件名
      cb(null, uuid + extname(file.originalname));
    },
  }),
};
const fileUploadOptions = {
  limits: {
    fileSize: env.UPLOAD_IMG_MAX_FILE_SIZE, // 2MB
  },
  fileFilter: (req, file, cb) => {
    const allowedFileTypes = Object.values(env.UPLOAD_FILE_MAP);
    const fileType =
      env.UPLOAD_FILE_MAP[file.originalname.split('.').pop().toLowerCase()];
    if (allowedFileTypes.includes(fileType)) {
      // Allow storage of file
      cb(null, true);
    } else {
      // Reject file
      cb(
        new HttpException(
          `Unsupported file type ${extname(file.originalname)}`,
          HttpStatus.BAD_REQUEST,
        ),
        false,
      );
    }
  },
  storage: diskStorage({
    destination: `./uploads/files/${getCurrentDate(false)}`,
    filename: (req, file, cb) => {
      const uuid = req['requestId'] || uuid4();
      // Generate a unique filename with the original extension
      cb(null, uuid + extname(file.originalname));
    },
  }),
};
@ApiTags('上传')
@Controller('upload')
export class UploadController {
  @Public()
  @Post('image')
  @ApiBody({ description: '上传图片', type: UploadImageDto })
  @ApiConsumes('multipart/form-data')
  @ApiOperation({
    summary: '上传图片',
    description: `支持格式: <b>${env.UPLOAD_IMG_EXT.join(', ')}</b> <br> 支持最大: <b>${env.UPLOAD_IMG_MAX_FILE_SIZE} KB</b>`,
  })
  @ApiResponse({ type: Response })
  @UseInterceptors(FileInterceptor('image', imageUploadOptions))
  async uploadImage(
    @UploadedFile() image: Express.Multer.File,
  ): Promise<Response> {
    // 将 path 中的反斜杠替换为正斜杠
    const fileUrl = image.path.replace(/\\/g, '/');
    return Response.success({ ...image, fileUrl });
  }
  @Public()
  @Post('video')
  @ApiBody({ description: '上传视频', type: UploadFileDto })
  @ApiConsumes('multipart/form-data')
  @ApiOperation({
    summary: '上传视频',
    description: `支持格式: <b>${env.UPLOAD_VIDEO_EXT.join(', ')}</b> <br> 支持最大: <b>${env.UPLOAD_VIDEO_MAX_FILE_SIZE / (1024 * 1024)} MB</b>`,
  })
  @ApiResponse({ type: Response })
  @UseInterceptors(FileInterceptor('video', videoUploadOptions))
  async uploadVideo(
    @UploadedFile() video: Express.Multer.File,
  ): Promise<Response> {
    // 将 path 中的反斜杠替换为正斜杠
    const fileUrl = video.path.replace(/\\/g, '/');
    return Response.success({ ...video, fileUrl });
  }

  @Public()
  @Post('file')
  @ApiBody({ description: '上传文件', type: UploadFileDto })
  @ApiConsumes('multipart/form-data')
  @ApiOperation({
    summary: '上传文件',
    description: `支持格式: <b>${env.UPLOAD_FILE_EXT.join(', ')}</b> 支持最大: <b>${env.UPLOAD_IMG_MAX_FILE_SIZE} KB</b>`,
  })
  @ApiResponse({ type: Response })
  @UseInterceptors(FileInterceptor('file', fileUploadOptions))
  async uploadFile(
    @UploadedFile() file: Express.Multer.File,
  ): Promise<Response> {
    // 将 path 中的反斜杠替换为正斜杠
    const fileUrl = file.path.replace(/\\/g, '/');
    return Response.success({ ...file, fileUrl });
  }
}
